package com.cicdi.core.util;

import com.alaya.contracts.ppos.abi.Function;
import com.alaya.contracts.ppos.dto.enums.StakingAmountType;
import com.alaya.contracts.ppos.utils.EncoderUtils;
import com.alaya.crypto.Credentials;
import com.alaya.parameters.NetworkParameters;
import com.alaya.utils.Convert;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

/**
 * 委托类工具
 *
 * @author haypo
 * @date 2020/12/2
 */
@Slf4j
public class DelegateUtil {
    private final SendUtil sendUtil;

    public DelegateUtil(String url) {
        sendUtil = new SendUtil(url);
    }

    /**
     * 将多个钱包快速委托给单个节点
     *
     * @param nodeId          节点id
     * @param credentialsList 钱包列表
     * @param atpAmount       委托金额，单位为atp
     * @param st              使用自由金额或者锁仓金额
     */
    public void fastDelegateWithMidGas(String nodeId, List<Credentials> credentialsList, BigDecimal atpAmount, StakingAmountType st) throws IOException {
        if (atpAmount.doubleValue() < Common.minDelegate) {
            return;
        }
        for (Credentials credentials : credentialsList) {
            fastDelegateWithMidGas(nodeId, credentials, atpAmount, st);
        }
    }

    /**
     * 将单个钱包快速委托给多个节点
     *
     * @param nodeIds     节点列表
     * @param credentials 钱包
     * @param atpAmount   委托金额，单位为atp
     * @param st          使用自由金额或者锁仓金额
     */
    public void fastDelegateWithMidGas(List<String> nodeIds, Credentials credentials, BigDecimal atpAmount, StakingAmountType st) throws IOException {
        if (atpAmount.doubleValue() < Common.minDelegate) {
            return;
        }
        long nonce = NonceUtil.getNonce(sendUtil.web3jService, credentials).longValue();
        for (String nodeId : nodeIds) {
            fastDelegateWithMidGas(nodeId, credentials, atpAmount, nonce++, st);
        }
    }

    /**
     * 将单个钱包快速委托给单个节点，自动获取nonce
     *
     * @param nodeId      节点id
     * @param credentials 钱包
     * @param atpAmount   委托金额，单位为atp
     * @param st          使用自由金额或者锁仓金额
     */
    public void fastDelegateWithMidGas(String nodeId, Credentials credentials, BigDecimal atpAmount, StakingAmountType st) throws IOException {
        long nonce = NonceUtil.getNonce(sendUtil.web3jService, credentials).longValue();
        fastDelegateWithMidGas(nodeId, credentials, atpAmount, nonce, st);
    }

    /**
     * 将单个钱包快速委托给单个节点，需要提供nonce
     *
     * @param nodeId      节点id
     * @param credentials 钱包
     * @param atpAmount   委托金额，单位为atp
     * @param nonce       nonce值
     * @param st          使用自由金额或者锁仓金额
     */
    public void fastDelegateWithMidGas(String nodeId, Credentials credentials, BigDecimal atpAmount, long nonce, StakingAmountType st) {
        if (atpAmount.doubleValue() < Common.minDelegate) {
            return;
        }
        BigDecimal vonAmount = Convert.toVon(MathUtil.round6(atpAmount), Convert.Unit.ATP);
        try {
            Function function = FunctionUtil.createDelegateFunction(nodeId, st, vonAmount.toBigIntegerExact());
            String data = EncoderUtils.functionEncoder(function);
            String contractAddressOfStaking = NetworkParameters.getPposContractAddressOfStaking(NetworkParameters.CurrentNetwork.getChainId());
            sendUtil.fastSend(credentials, nonce, BigDecimal.ZERO, contractAddressOfStaking, data, Common.MID_GAS_PROVIDER);
            log.info("地址：{} 委托给：{} 金额：{}",
                    credentials.getAddress(), nodeId, MathUtil.round6(atpAmount));
        } catch (Exception e) {
            log.error(e.getLocalizedMessage(), e);
        }
    }
}
